#include "keyboard.hh"

Keyboard::Keyboard (bool* go, Camera* cam, Mouse* m):
  keystate_ (0),
  e_ (),
  go_ (go) ,
  cam_ (cam),
  m_ (m)
{
  parse_file ();

  chat_active_ = false;
  chat_enable_ = false;

  e_.type = 0;
  mode_FPS = false;

  init_actions ();

  ActionQueue* aq = ActionQueue::Instance ();
  queue_ = aq->queue_get ();
  SDL_EnableKeyRepeat (1, 10);

  clicked_ = new bool[5];
  for (int i = 0; i < 5; ++i)
    clicked_[i] = false;
}

void
Keyboard::init_actions ()
{
  // init up action
  act_RTS_["UP"] = new ActionRtsMove (Vector3f (1, 0, 0));
  act_FPS_["UP"] = new ActionFpsMove (Vector3f (1, 0, 0));

  // init down action
  act_RTS_["DOWN"] = new ActionRtsMove (Vector3f (-1, 0, 0));
  act_FPS_["DOWN"] = new ActionFpsMove (Vector3f (-1, 0, 0));

  // init front action
  act_RTS_["FRONT"] = new ActionRtsMove (Vector3f (0, 0, 1));
  act_FPS_["FRONT"] = new ActionFpsMove (Vector3f (0, 0, 1));

  // init back action
  act_RTS_["BACK"] = new ActionRtsMove (Vector3f (0, 0, -1));
  act_FPS_["BACK"] = new ActionFpsMove (Vector3f (0, 0, -1));

  // init left action
  act_RTS_["LEFT"] = new ActionRtsMove (Vector3f (0, -1, 0));
  act_FPS_["LEFT"] = new ActionFpsMove (Vector3f (0, -1, 0));

  // init right action
  act_RTS_["RIGHT"] = new ActionRtsMove (Vector3f (0, 1, 0));
  act_FPS_["RIGHT"] = new ActionFpsMove (Vector3f (0, 1, 0));

  //init rotate action
  act_RTS_["ROTATEX"] = new ActionRtsRotateObj (Vector3d (0, 0, 10));
  act_RTS_["ROTATEY"] = new ActionRtsRotateObj (Vector3d (0, 10, 0));
  act_RTS_["ROTATEZ"] = new ActionRtsRotateObj (Vector3d (10, 0, 0));

  // init exit action
  act_RTS_["EXIT"] = new ActionRtsExit;
  act_FPS_["EXIT"] = new ActionFpsExit;

  // init move obj
  act_RTS_["OBJ_FRONT"] = new ActionRtsMoveObj (Vector3f (1, 0, 0));
  act_RTS_["OBJ_BACK"] = new ActionRtsMoveObj (Vector3f (-1, 0, 0));
  act_RTS_["OBJ_LEFT"] = new ActionRtsMoveObj (Vector3f (0, -1, 0));
  act_RTS_["OBJ_RIGHT"] = new ActionRtsMoveObj (Vector3f (0, 1, 0));
  act_RTS_["OBJ_UP"] = new ActionRtsMoveObj (Vector3f (0, 0, 1));
  act_RTS_["OBJ_DOWN"] = new ActionRtsMoveObj (Vector3f (0, 0, -1));

  // init chat
  act_RTS_["CHAT"] = new ActionChat ();
  act_FPS_["CHAT"] = new ActionChat ();

  act_RTS_["CHAT_ENABLE_SWITCH"] = new ActionChatES ();
  act_FPS_["CHAT_ENABLE_SWITCH"] = new ActionChatES ();
}

Keyboard::~Keyboard ()
{
  delete[] clicked_;
}

void
Keyboard::switch_chat (SDLKey key)
{
  std::map<SDLKey, std::string>::iterator it;

  if (mode_FPS)
    {
      it = keyconf_FPS_.find (key);
      if (it != keyconf_FPS_.end () &&
	  it->second == "CHAT")
	queue_->push (act_FPS_[(*it).second]);
    }
  else
    {
      it = keyconf_RTS_.find (key);
      if (it != keyconf_RTS_.end () &&
	  it->second == "CHAT")
	queue_->push (act_RTS_[(*it).second]);
    }
}

void
Keyboard::enable_chat_switch (SDLKey key)
{
  std::map<SDLKey, std::string>::iterator it;

  if (mode_FPS)
    {
      it = keyconf_FPS_.find (key);
      if (it != keyconf_FPS_.end () &&
	  it->second == "CHAT")
	queue_->push (act_FPS_["CHAT_ENABLE_SWITCH"]);
    }
  else
    {
      it = keyconf_RTS_.find (key);
      if (it != keyconf_RTS_.end () &&
	  it->second == "CHAT")
	queue_->push (act_RTS_["CHAT_ENABLE_SWITCH"]);
    }
}

void
Keyboard::handle_chat (const SDL_Event& e)
{
  if (e.key.keysym.sym == SDLK_BACKSPACE)
    queue_->push (new ActionChatDel ());
  else if (e.key.keysym.sym == SDLK_LEFT)
    queue_->push (new ActionChatCurMove (-1));
  else if (e.key.keysym.sym == SDLK_RIGHT)
    queue_->push (new ActionChatCurMove (1));
  else if (e.key.keysym.unicode)
    queue_->push(new ActionChatAdd (e.key.keysym.unicode));
}

void
Keyboard::do_actions ()
{
  std::map<SDLKey, std::string>::iterator it;

  if (mode_FPS)
    {
      for (it = keyconf_FPS_.begin (); it != keyconf_FPS_.end (); ++it)
	if (keystate_[(*it).first] && (*it).second != "CHAT")
	  queue_->push (act_FPS_[(*it).second]);
    }
  else
    {
      for (it = keyconf_RTS_.begin (); it != keyconf_RTS_.end (); ++it)
	if (keystate_[(*it).first] && (*it).second != "CHAT")
	  queue_->push (act_RTS_[(*it).second]);
    }
}

void
Keyboard::event (float elapsed_time)
{
  cam_->time_set (elapsed_time);

  Vector3d vect;
  std::map<SDLKey, std::string>::iterator it;

  vect.val_set (0, 0, 0);

  keystate_ = SDL_GetKeyState (0);

  if (!chat_active_)
    do_actions ();

  while (SDL_PollEvent (&e_))
  {
    if (e_.type == SDL_KEYDOWN) // event de touche clavier
      {
	if (chat_enable_)
	  switch_chat (e_.key.keysym.sym);

	if (chat_active_)
	  handle_chat (e_);
      }
    else if (e_.type == SDL_MOUSEBUTTONDOWN) // event de click souris
      {
	m_->button_pressed (e_.button.button, cam_);
	clicked_[e_.button.button - 1] = true;
      }
    else if (e_.type == SDL_MOUSEBUTTONUP) // event de release click souris
      {
	m_->button_released (e_.button.button, cam_);
	clicked_[e_.button.button - 1] = false;
      }
    else if (e_.type == SDL_MOUSEMOTION) // event de deplacement de la souris
      {
	cam_->set_angles (e_.motion.xrel * 0.002,
			  e_.motion.yrel * 0.002);
      }
    else if (e_.type == SDL_QUIT) // event de fin de programme
      *go_ = false;
    else if (e_.type == SDL_KEYUP)
      enable_chat_switch (e_.key.keysym.sym);

    for (int i = 0; i < 5; ++i)
      if (clicked_[i])
    	m_->catch_mouse_pos (i + 1, cam_);
  }
}

void
Keyboard::parse_file ()
{
  std::ifstream file ("content/keyboard.conf");

  if (!file.is_open ())
  {
    std::cerr << "No content/keyboard.conf file." << std::endl;
    assert (false);
  }

  std::string tmp;
  int pos = 0;
  std::string input;

  std::string key;
  int offset = 0;
  SDLKey s;
  bool is_FPS = false;

  while (!file.eof ())
    {
      file >> tmp;

      if (tmp == "FPS")
	{
	  is_FPS = true;
	  continue;
	}
      else if (tmp == "RTS")
	{
	  is_FPS = false;
	  continue;
	}

      pos = tmp.find ('=');
      input = tmp.substr (pos + 1);
      tmp = tmp.substr (0, pos);
      offset = 0;

      while ((pos = input.find (',', offset)) != -1)
	{
	  key = input.substr (offset, pos - offset);
	  offset = pos + 1;

	  if (key.size () == 1)
	    s = (SDLKey) key[0];
	  else
	    {
	      if (key == "up")
		s = SDLK_UP;
	      else if (key == "down")
		s = SDLK_DOWN;
	      else if (key == "right")
		s = SDLK_RIGHT;
	      else if (key == "left")
		s = SDLK_LEFT;
	      else if (key == "escape")
		s = SDLK_ESCAPE;
	      else if (key == "enter")
		s = SDLK_KP_ENTER;
	      else if (key == "return")
		s = SDLK_RETURN;
	    }

	  if (is_FPS)
	    keyconf_FPS_[s] = tmp;
	  else
	    keyconf_RTS_[s] = tmp;
	}

      key = input.substr (offset);

      if (key.size () == 1)
	s = (SDLKey) key[0];
      else
	{
	  if (key == "up")
	    s = SDLK_UP;
	  else if (key == "down")
	    s = SDLK_DOWN;
	  else if (key == "right")
	    s = SDLK_RIGHT;
	  else if (key == "left")
	    s = SDLK_LEFT;
	  else if (key == "escape")
	    s = SDLK_ESCAPE;
	  else if (key == "enter")
	    s = SDLK_KP_ENTER;
	  else if (key == "return")
	    s = SDLK_RETURN;
	}

      if (is_FPS)
	keyconf_FPS_[s] = tmp;
      else
	keyconf_RTS_[s] = tmp;
    }

  file.close ();
}
